package com.perceptivesoftware.licensing.client.dialogs.useradmin.plugin.role;

import java.util.ArrayList;
import java.util.List;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.perceptivesoftware.licensing.client.LicensingAsyncCallback;
import com.perceptivesoftware.licensing.client.LicensingRPCFactory;
import com.perceptivesoftware.licensing.client.PerceptiveUISession;
import com.perceptivesoftware.licensing.client.common.DirtyCallbackHandler;
import com.perceptivesoftware.licensing.client.common.util.NPAction;
import com.perceptivesoftware.licensing.client.common.util.NPType;
import com.perceptivesoftware.licensing.client.common.util.PerceptivePermission;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.PermissionsTreePanel;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.SecurityManagerView;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.callbackhandlers.AddCallbackHandler;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.callbackhandlers.DeleteCallbackHandler;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.callbackhandlers.ItemSelectedCallbackHandler;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.callbackhandlers.RenameCallbackHandler;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.callbackhandlers.SaveCallbackHandler;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.callbackhandlers.SecurityManagerAsyncCallback;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.interfaces.Addable;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.interfaces.Deletable;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.interfaces.Parent;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.interfaces.Renamable;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.interfaces.Saveable;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.plugin.SecurityManagerNavItem;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.plugin.SecurityManagerPlugin;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.plugin.user.PermissionsSaveDTO;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.plugin.user.UserNavItem;

public class RolePlugin extends SecurityManagerPlugin<RoleNavItem> implements Parent, Addable, Deletable, Renamable, Saveable {

	private RoleView roleComposite;
	private DirtyCallbackHandler dirtyCallbackHandler;
	private RoleDTO roleDTO;
	private PermissionsTreePanel permissionsTreePanel;
	private final Boolean hasPermissionPermission = PerceptiveUISession.getInstance().hasPermission(new PerceptivePermission(NPType.ADMIN, NPAction.MANAGE_SECURITY));

	@Override
	public void init() {
		if (hasPermissionPermission) {
			permissionsTreePanel = new PermissionsTreePanel(dirtyCallbackHandler, true);
		}
		roleComposite = new RoleView(permissionsTreePanel);
	}

	@Override
	public String getIconStyle() {
		return "nav-icon-role";
	}

	@Override
	public SecurityManagerView getView() {
		return roleComposite;
	}

	@Override
	protected void itemSelected(final RoleNavItem rni, final ItemSelectedCallbackHandler isch) {
		if (!hasPermissionPermission) {
			isch.doneRendering();
			return;
		}
		LicensingRPCFactory.getSecurityService(true).getRoleDTO(rni.getRoleCode(), new SecurityManagerAsyncCallback<RoleDTO>() {

			@Override
			public void onSuccess(final RoleDTO _roleDTO) {
				roleDTO = _roleDTO;
				permissionsTreePanel.setPermissions(roleDTO.getPermissionsDTO());
				isch.doneRendering();
			}
		});
	}

	@Override
	public List<SecurityManagerNavItem> getChildren(final SecurityManagerNavItem parent) {
		final RoleNavItem role = (RoleNavItem) parent;
		final ArrayList<SecurityManagerNavItem> returnusers = new ArrayList<SecurityManagerNavItem>();
		for (final UserNavItem userNavItem : PerceptiveUISession.getInstance().getAllUsers()) {
			if (userNavItem.getRoleCode() != null && userNavItem.getRoleCode().equals(role.getRoleCode())) {
				returnusers.add(userNavItem);
			}
		}
		return returnusers;
	}

	@Override
	public void add(final String name, final SecurityManagerNavItem parent, final AddCallbackHandler ach) {
		final RoleNavItem roleNavItem = (RoleNavItem) parent;
		LicensingRPCFactory.getSecurityService(true).createUser(name, roleNavItem.getRoleCode(), false, new SecurityManagerAsyncCallback<UserNavItem>() {

			@Override
			public void onSuccess(final UserNavItem userNavItem) {
				if (userNavItem == null) {
					ach.addFailed("Does another user already exist with this name?");
				}
				else {
					PerceptiveUISession.getInstance().getAllUsers().add(userNavItem);
					ach.added(userNavItem);
				}
			}
		});
	}

	@Override
	public String getAddIconStyle() {
		return "nav-icon-user-add";
	}

	@Override
	public String getAddName() {
		return "User";
	}

	@Override
	public void delete(final SecurityManagerNavItem ani, final DeleteCallbackHandler dch) {
		final RoleNavItem rni = (RoleNavItem) ani;
		LicensingRPCFactory.getSecurityService(true).deleteRole(rni.getRoleCode(), new SecurityManagerAsyncCallback<String>() {

			@Override
			public void onSuccess(final String failureReason) {
				if (failureReason == null) {
					dch.deleted();
				}
				else {
					dch.deleteFailed(failureReason);
				}
			}
		});
	}

	@Override
	public String getDeleteIconStyle() {
		return "nav-icon-role-delete";
	}

	@Override
	public String getRenameIconStyle() {
		return "nav-icon-role-rename";
	}

	@Override
	public void rename(final String name, final SecurityManagerNavItem itemToRename, final RenameCallbackHandler rch) {
		final RoleNavItem rni = (RoleNavItem) itemToRename;
		LicensingRPCFactory.getSecurityService(true).renameRole(rni.getRoleCode(), name, new SecurityManagerAsyncCallback<String>() {

			@Override
			public void onSuccess(final String failureReason) {
				if (failureReason == null) {
					rch.renamed(name);
				}
				else {
					rch.renameFailed(failureReason);
				}
			}
		});
	}

	@Override
	public void dirtyCallbackHandler(final DirtyCallbackHandler dirtyCallbackHandler) {
		this.dirtyCallbackHandler = dirtyCallbackHandler;
	}

	@Override
	public void save(final SaveCallbackHandler sch) {
		final List<PerceptivePermission> dirtyPermissions = roleDTO.getPermissionsDTO().getDirtyPermissions();
		List<PerceptivePermission> cascadePermissions = new ArrayList<PerceptivePermission>();
		if (roleComposite.getCascadeToChildrenChecked()) {
			cascadePermissions = roleDTO.getPermissionsDTO().getCascadePermissions();
		}
		if ((dirtyPermissions.size() + cascadePermissions.size()) == 0) {
			sch.saved();
			return;
		}
		String whyDirty = "Changed Permissions:";
		for (final PerceptivePermission np : dirtyPermissions) {
			whyDirty += np.whyDirty();
			whyDirty += "\n";
		}
		whyDirty += "\nCascade Permissions:";
		for (final PerceptivePermission np : cascadePermissions) {
			whyDirty += np.getType().toString() + ":" + np.getAction().toString();
			if (np.getItemCode() != null) {
				whyDirty += np.getItemCode() + ":";
			}
			whyDirty += np.getHasPermission().toString();
			whyDirty += "\n";
		}

		/*
		 * if (!Window.confirm(whyDirty)) { sch.saveFailed(); return; }
		 */

		LicensingRPCFactory.getSecurityService(true).saveRolePermissions(roleDTO.getRoleCode(), dirtyPermissions, cascadePermissions,
				new LicensingAsyncCallback<PermissionsSaveDTO>() {

					@Override
					public void onSuccess(final PermissionsSaveDTO success) {
						if (success.isSuccess()) {
							for (final PerceptivePermission np : dirtyPermissions) {
								np.savedToDatabase();
							}
							permissionsTreePanel.setPermissions(roleDTO.getPermissionsDTO());
							sch.saved();
							if (success.getPrompt() != null) {
								MessageBox.info("Permissions", success.getPrompt(), null);
							}
						}
						else {
							sch.saveFailed();
						}
					}

					@Override
					public void onPerceptiveFailure(@SuppressWarnings("unused") final Throwable caught) {
						sch.saveFailed();
					}
				});
	}

	@Override
	public Boolean canAdd(@SuppressWarnings("unused") final SecurityManagerNavItem parent) {
		return PerceptiveUISession.getInstance().hasPermission(new PerceptivePermission(NPType.ADMIN, NPAction.MANAGE_SECURITY));
	}

	@Override
	public Boolean canDelete(@SuppressWarnings("unused") final SecurityManagerNavItem ani) {
		return PerceptiveUISession.getInstance().hasPermission(new PerceptivePermission(NPType.ADMIN, NPAction.MANAGE_SECURITY));
	}

	@Override
	public Boolean canRename(@SuppressWarnings("unused") final SecurityManagerNavItem ani) {
		return PerceptiveUISession.getInstance().hasPermission(new PerceptivePermission(NPType.ADMIN, NPAction.MANAGE_SECURITY));
	}

	@Override
	public String getRenameName() {
		return "Role";
	}

}
